home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
iconv8_s.arc
/
ICONT.ARC
/
TCODE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-28
|
25KB
|
1,075 lines
/*
* tcode.c -- translator functions for traversing parse trees and generating
* code.
*/
#include "..\h\config.h"
#include "general.h"
#include "tproto.h"
#include "globals.h"
#include "trans.h"
#include "token.h"
#include "tree.h"
#include "tsym.h"
/*
* Prototypes.
*/
hidden int alclab Params((int n));
hidden novalue binop Params((int op));
hidden novalue emit Params((char *s));
hidden novalue emitl Params((char *s,int a));
hidden novalue emitlab Params((int l));
hidden novalue emitn Params((char *s,int a));
hidden novalue emits Params((char *s,char *a));
hidden novalue setloc Params((nodeptr n));
hidden int traverse Params((nodeptr t));
hidden novalue unopa Params((int op, nodeptr t));
hidden novalue unopb Params((int op));
extern int tfatals;
extern int nocode;
extern char *comfile;
/*
* Code generator parameters.
*/
#define LoopDepth 20 /* max. depth of nested loops */
#define CaseDepth 10 /* max. depth of nested case statements */
#define CreatDepth 10 /* max. depth of nested create statements */
/*
* loopstk structures hold information about nested loops.
*/
struct loopstk {
int nextlab; /* label for next exit */
int breaklab; /* label for break exit */
int markcount; /* number of marks */
int ltype; /* loop type */
};
/*
* casestk structure hold information about case statements.
*/
struct casestk {
int endlab; /* label for exit from case statement */
nodeptr deftree; /* pointer to tree for default clause */
};
/*
* creatstk structures hold information about create statements.
*/
struct creatstk {
int nextlab; /* previous value of nextlab */
int breaklab; /* previous value of breaklab */
};
static int nextlab; /* next label allocated by alclab() */
/*
* codegen - traverse tree t, generating code.
*/
novalue codegen(t)
nodeptr t;
{
nextlab = 1;
traverse(t);
}
/*
* traverse - traverse tree rooted at t and generate code. This is just
* plug and chug code for each of the node types.
*/
static int traverse(t)
register nodeptr t;
{
register int lab, n, i;
struct loopstk loopsave;
static struct loopstk loopstk[LoopDepth]; /* loop stack */
static struct loopstk *loopsp;
static struct casestk casestk[CaseDepth]; /* case stack */
static struct casestk *casesp;
static struct creatstk creatstk[CreatDepth]; /* create stack */
static struct creatstk *creatsp;
n = 1;
switch (TType(t)) {
case N_Activat: /* co-expression activation */
if (Val0(Tree0(t)) == AUGACT) {
emit("pnull");
}
traverse(Tree2(t)); /* evaluate result expression */
if (Val0(Tree0(t)) == AUGACT)
emit("sdup");
traverse(Tree1(t)); /* evaluate activate expression */
setloc(t);
emit("coact");
if (Val0(Tree0(t)) == AUGACT)
emit("asgn");
break;
case N_Alt: /* alternation */
lab = alclab(2);
emitl("mark", lab);
loopsp->markcount++;
traverse(Tree0(t)); /* evaluate first alternative */
loopsp->markcount--;
emit("esusp"); /* and suspend with its result */
emitl("goto", lab+1);
emitlab(lab);
traverse(Tree1(t)); /* evaluate second alternative */
emitlab(lab+1);
break;
case N_Augop: /* augmented assignment */
case N_Binop: /* or a binary operator */
emit("pnull");
traverse(Tree1(t));
if (TType(t) == N_Augop)
emit("dup");
traverse(Tree2(t));
setloc(t);
binop((int)Val0(Tree0(t)));
break;
case N_Bar: /* repeated alternation */
lab = alclab(1);
emitlab(lab);
emit("mark0"); /* fail if expr fails first time */
loopsp->markcount++;
traverse(Tree0(t)); /* evaluate first alternative */
loopsp->markcount--;
emitl("chfail", lab); /* change to loop on failure */
emit("esusp"); /* suspend result */
break;
case N_Break: /* break expression */
if (loopsp->breaklab <= 0)
nfatal(t, "invalid context for break");
else {
for (i = 0; i < loopsp->markcount; i++)
emit("unmark");
loopsave = *loopsp--;
traverse(Tree0(t));
*++loopsp = loopsave;
emitl("goto", loopsp->breaklab);
}
break;
case N_Case: /* case expression */
lab = alclab(1);
casesp++;
casesp->endlab = lab;
casesp->deftree = NULL;
emit("mark0");
loopsp->markcount++;
traverse(Tree0(t)); /* evaluate control expression */
loopsp->markcount--;
emit("eret");
traverse(Tree1(t)); /* do rest of case (CLIST) */
if (casesp->deftree != NULL) { /* evaluate default clause */
emit("pop");
traverse(casesp->deftree);
}
else
emit("efail");
emitlab(lab); /* end label */
casesp--;
break;
case N_Ccls: /* case expression clause */
if (TType(Tree0(t)) == N_Res && /* default clause */
Val0(Tree0(t)) == DEFAULT) {
if (casesp->deftree != NULL)
nfatal(t, "more than one default clause");
else
casesp->deftree = Tree1(t);
}
else { /* case clause */
lab = alclab(1);
emitl("mark", lab);
loopsp->markcount++;
emit("ccase");
traverse(Tree0(t)); /* evaluate selector */
setloc(t);
emit("eqv");
loopsp->markcount--;
emit("unmark");
emit("pop");
traverse(Tree1(t)); /* evaluate expression */
emitl("goto", casesp->endlab); /* goto end label */
emitlab(lab); /* label for next clause */
}
break;
case N_Clist: /* list of case clauses */
traverse(Tree0(t));
traverse(Tree1(t));
break;
case N_Conj: /* conjunction */
if (Val0(Tree0(t)) == AUGAND) {
emit("pnull");
}
traverse(Tree1(t));
if (Val0(Tree0(t)) != AUGAND)
emit("pop");
traverse(Tree2(t));
if (Val0(Tree0(t)) == AUGAND) {
setloc(t);
emit("asgn");
}
break;
case N_Create: /* create expression */
creatsp++;
creatsp->nextlab = loopsp->nextlab;
creatsp->breaklab = loopsp->breaklab;
loopsp->nextlab = 0; /* make break and next illegal */
loopsp->breaklab = 0;
lab = alclab(3);
emitl("goto", lab+2); /* skip over code for co-expression */
emitlab(lab); /* entry point */
emit("pop"); /* pop the result from activation */
emitl("mark", lab+1);
loopsp->markcount++;
traverse(Tree0(t)); /* traverse code for co-expression */
loopsp->markcount--;
setloc(t);
emit("coret"); /* return to activator */
emit("efail"); /* drive co-expression */
emitlab(lab+1); /* loop on exhaustion */
emit("cofail"); /* and fail each time */
emitl("goto", lab+1);
emitlab(lab+2);
emitl("create", lab); /* create entry block */
loopsp->nextlab = creatsp->nextlab; /* legalize break and next */
loopsp->breaklab = creatsp->breaklab;
creatsp--;
break;
case N_Cset: /* cset literal */
emitn("cset", (int)Val0(t));
break;
case N_Elist: /* expression list */
n = traverse(Tree0(t));
n += traverse(Tree1(t));
break;
case N_Empty: /* a missing expression */
emit("pnull");
break;
case N_Field: /* field reference */
emit("pnull");
traverse(Tree0(t));
setloc(t);
emits("field", Str0(Tree1(t)));
break;
case N_Id: /* identifier */
emitn("var", (int)Val0(t));
break;
case N_If: /* if expression */
if (TType(Tree2(t)) == N_Empty) {
lab = 0;
emit("mark0");
}
else {
lab = alclab(2);
emitl("mark", lab);
}
loopsp->markcount++;
traverse(Tree0(t));
loopsp->markcount--;
emit("unmark");
traverse(Tree1(t));
if (lab > 0) {
emitl("goto", lab+1);
emitlab(lab);
traverse(Tree2(t));
emitlab(lab+1);
}
break;
case N_Int: /* integer literal */
emitn("int", (int)Val0(t));
break;
case N_Apply: /* application */
traverse(Tree0(t));
traverse(Tree1(